﻿using System;
using System.ServiceModel.Channels;
using System.ServiceModel;
using System.Transactions;

namespace Microsoft.Biztalk.Adapters.Wcf.NullBinding
{
    class NullInputChannel : NullChannelBase, IInputChannel
    {
        public NullInputChannel(ChannelManagerBase manager, NullBindingProperties props)
            : base(manager, props)
        {
        }

        public IAsyncResult BeginReceive(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return new NullAsyncResult(EvaluateTimeOut(timeout), callback, state);
        }

        public IAsyncResult BeginReceive(AsyncCallback callback, object state)
        {
            return new NullAsyncResult(EvaluateTimeOut(TimeSpan.MaxValue), callback, state);
        }

        public IAsyncResult BeginTryReceive(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return new NullAsyncResult(EvaluateTimeOut(timeout), callback, state);
        }

        public IAsyncResult BeginWaitForMessage(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return new NullAsyncResult(callback, state);
        }

        public Message EndReceive(IAsyncResult result)
        {
            Message message = null;
            this.InternalTransaction = GetMessageAndTransaction(out message, false);            
            return message;
        }

        public bool EndTryReceive(IAsyncResult result, out Message message)
        {
            message = EndReceive(result);
            return true;
        }

        public bool EndWaitForMessage(IAsyncResult result)
        {
            return true;
        }

        public EndpointAddress LocalAddress
        {
            get { return new EndpointAddress(Helpers.Address); }
        }

        public Message Receive(TimeSpan timeout)
        {
            return (EndReceive(BeginReceive(timeout, null, null)));
        }

        public Message Receive()
        {
            return (EndReceive(BeginReceive(null, null)));
        }

        public bool TryReceive(TimeSpan timeout, out Message message)
        {
            return (EndTryReceive(BeginReceive(null, null), out message));
        }

        public bool WaitForMessage(TimeSpan timeout)
        {
            return true;
        }
    }

    class NullReplyChannel : NullChannelBase, IReplyChannel
    {
        public NullReplyChannel(ChannelManagerBase manager, NullBindingProperties props)
            : base(manager, props)
        {
        }

        public IAsyncResult BeginReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return new NullAsyncResult(EvaluateTimeOut(timeout), callback, state);
        }

        public IAsyncResult BeginReceiveRequest(AsyncCallback callback, object state)
        {
            return new NullAsyncResult(EvaluateTimeOut(this.DefaultReceiveTimeout), callback, state);
        }

        public IAsyncResult BeginTryReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return new NullAsyncResult(EvaluateTimeOut(timeout), callback, state);
        }

        public IAsyncResult BeginWaitForRequest(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return new NullAsyncResult(callback, state);
        }

        public RequestContext EndReceiveRequest(IAsyncResult result)
        {
            Message message;
            if (this.State == CommunicationState.Closed)
                return null;
            else
                return new NullRequestContext(GetMessageAndTransaction(out message, true), message, this.Properties.LogMessages);
        }

        public bool EndTryReceiveRequest(IAsyncResult result, out RequestContext context)
        {
            context = EndReceiveRequest(result);
            return true;
        }

        public bool EndWaitForRequest(IAsyncResult result)
        {
            return true;
        }

        public RequestContext ReceiveRequest(TimeSpan timeout)
        {
            return EndReceiveRequest(BeginReceiveRequest(timeout,null, null));
        }

        public RequestContext ReceiveRequest()
        {
            return EndReceiveRequest(BeginReceiveRequest(this.DefaultReceiveTimeout, null, null));
        }

        public bool TryReceiveRequest(TimeSpan timeout, out RequestContext context)
        {
            return EndTryReceiveRequest(BeginTryReceiveRequest(timeout, null, null), out context);
        }

        public bool WaitForRequest(TimeSpan timeout)
        {
            return true;
        }

        public EndpointAddress LocalAddress
        {
            get { return new EndpointAddress(Helpers.Address); }
        }
    }

}
